﻿using System;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using DevelopersToolbox;

namespace RegExTools {
    public partial class RegExControl : UserControl, IExecutableTool {
        private static readonly Color[] CAPTURE_COLORS = new[] { Color.Red, Color.Yellow, Color.LightBlue, Color.LightGreen };

        public RegExControl() {
            InitializeComponent();
            _toolTip.SetToolTip(_regexOptionIgnoreCase, "Specifies case-insensitive matching.");
            _toolTip.SetToolTip(_regexOptionIgnorePatternWhitespace, "Eliminates unescaped white space from the pattern and enables comments marked with #.");
            _toolTip.SetToolTip(_regexOptionMultiline, "Multiline mode. Changes the meaning of ^ and $ so they match at the beginning and end, respectively, of any line, and not just the beginning and end of the entire string.");
            _toolTip.SetToolTip(_regexOptionRightToLeft, "Specifies that the search will be from right to left instead of from left to right.");
            _toolTip.SetToolTip(_regexOptionSingleLine, "Specifies single-line mode. Changes the meaning of the dot (.) so it matches every character (instead of every character except \n).");
            _toolTip.SetToolTip(_regexOptionExplicitCapture, "Specifies that the only valid captures are explicitly named or numbered groups of the form (?<name>…). This allows unnamed parentheses to act as noncapturing groups without the syntactic clumsiness of the expression (?:…).");
        }

        private void _executeButton_Click(object sender, EventArgs e) {
            Execute();
        }

        public void Execute() {
            try {
                string pattern = _regEx.Text.Trim();
                RegexOptions options = RegexOptions.None;
                if (_regexOptionIgnoreCase.Checked)
                    options |= RegexOptions.IgnoreCase;
                if (_regexOptionIgnorePatternWhitespace.Checked)
                    options |= RegexOptions.IgnorePatternWhitespace;
                if (_regexOptionMultiline.Checked)
                    options |= RegexOptions.Multiline;
                if (_regexOptionRightToLeft.Checked)
                    options |= RegexOptions.RightToLeft;
                if (_regexOptionSingleLine.Checked)
                    options |= RegexOptions.Singleline;
                if (_regexOptionExplicitCapture.Checked)
                    options |= RegexOptions.ExplicitCapture;
                string input = _testData.Text.Trim();

                Regex regex = new Regex(pattern, options);
                MatchCollection matches = regex.Matches(input);
                StringBuilder sb = new StringBuilder();

                sb.AppendLine(input);
                sb.AppendLine("");
                sb.AppendLine("");

                // create list of groups and captures
                int index = 1;
                int count = matches.Count;
                foreach (Match match in matches) {
                    sb.AppendLine(string.Format("--- ({0}/{1}) ------------------------------", index, count));
                    if (match.Success) {
                        for (int groupIndex = 0; groupIndex < match.Groups.Count; groupIndex++) {
                            Group group = match.Groups[groupIndex];
                            string groupName = regex.GetGroupNames()[groupIndex];
                            string groupValue = group.Value;
                            string groupString = string.Format("Group{0}({1}) = [{2}]", groupIndex, groupName,
                                                               groupValue);
                            sb.AppendLine(groupString);
                            for (int captureIndex = 0; captureIndex < group.Captures.Count; captureIndex++) {
                                Capture capture = group.Captures[captureIndex];
                                string captureName = string.Format("Capture{0}", captureIndex);
                                string captureValue = capture.Value;
                                string captureString = string.Format("\t{0} = [{1}] Index={2}, Length={3}", captureName,
                                                                     captureValue, capture.Index, capture.Length);
                                sb.AppendLine(captureString);
                            }
                        }
                    }
                    else {
                        sb.AppendLine("Not a success");
                    }
                    index++;
                }
                _results.Text = sb.ToString();

                _results.SelectAll();
                _results.SelectionBackColor = _results.BackColor;

                // create pretty string of regex
                foreach (Match match in matches) {
                    int colorIndex = 0;
                    bool isFirstGroup = match.Groups.Count > 1 ? true : false;
                    foreach (Group group in match.Groups) {
                        if (!isFirstGroup) {
                            foreach (Capture capture in group.Captures) {
                                _results.Select(capture.Index, capture.Length);
                                _results.SelectionBackColor = CAPTURE_COLORS[colorIndex % CAPTURE_COLORS.Length];
                                colorIndex++;
                            }
                        }
                        isFirstGroup = false;
                    }
                }
            }
            catch (Exception ex) {
                _results.Text = ex.ToString();
            }
        }
    }
}